package com.ovopark.firecar.utils

import android.content.Context
import android.text.Spannable
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.TextUtils
import android.text.style.ForegroundColorSpan
import android.text.style.ScaleXSpan
import com.ovopark.firecar.R
import java.io.UnsupportedEncodingException
import java.math.BigDecimal
import java.net.URLEncoder
import java.text.DecimalFormat
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
import java.util.regex.Pattern

/**
 * String ContextUtils
 *
 * @author [Trinea](http://www.trinea.cn) 2011-7-22
 */
class StringUtils private constructor() {
    companion object {
        /**
         * 将半角字符转换为全角字符
         * 解决TextView 换行问题
         * 安卓默认数字、字母不能为第一行以后每行的开头字符，因为数字、字母为半角字符
         *
         * @param input
         * @return
         */
        fun ToSBC(input: String): String {
            val c = input.toCharArray()
            for (i in c.indices) {
                if (c[i] == ' ') {
                    c[i] = '\u3000'
                } else if (c[i] < '\u007f') {
                    c[i] = (c[i] + 65248)
                }
            }
            return String(c)
        }

        /**
         * 半角转换为全角
         *
         * @param input
         * @return
         */
        fun ToDBC(input: String): String {
            val c = input.toCharArray()
            for (i in c.indices) {
                if (c[i].toInt() == 12288) {
                    c[i] = 32.toChar()
                    continue
                }
                if (c[i].toInt() in 65281..65374) c[i] = (c[i] - 65248)
            }
            return String(c)
        }

        /**
         * 去除特殊字符或将所有中文标号替换为英文标号
         *
         * @param str
         * @return
         */
        fun stringFilter(str: String): String {
            var str = str
            str = str.replace("【".toRegex(), "[").replace("】".toRegex(), "]")
                .replace("！".toRegex(), "!").replace("：".toRegex(), ":") // 替换中文标号
            val regEx = "[『』]" // 清除掉特殊字符
            val p = Pattern.compile(regEx)
            val m = p.matcher(str)
            return m.replaceAll("").trim { it <= ' ' }
        }

        /**
         * is null or its length is 0 or it is made by common_line_space
         *
         *
         * <pre>
         * isBlank(null) = true;
         * isBlank(&quot;&quot;) = true;
         * isBlank(&quot;  &quot;) = true;
         * isBlank(&quot;a&quot;) = false;
         * isBlank(&quot;a &quot;) = false;
         * isBlank(&quot; a&quot;) = false;
         * isBlank(&quot;a b&quot;) = false;
        </pre> *
         *
         * @param str
         * @return if string is null or its size is 0 or it is made by common_line_space, return true, else return false.
         */
        @JvmStatic
        fun isBlank(str: String?): Boolean {
            return str == null || str.trim { it <= ' ' }.length == 0 || str == "null"
        }

        /**
         * is null or its length is 0
         *
         *
         * <pre>
         * isEmpty(null) = true;
         * isEmpty(&quot;&quot;) = true;
         * isEmpty(&quot;  &quot;) = false;
        </pre> *
         *
         * @param str
         * @return if string is null or its size is 0, return true, else return false.
         */
        @JvmStatic
        fun isEmpty(str: CharSequence?): Boolean {
            return str == null || str.length == 0
        }

        /**
         * compare two string
         *
         * @param actual
         * @param expected
         * @return
         * @see ObjectUtils.isEquals
         */
        fun isEquals(actual: String?, expected: String?): Boolean {
            return ObjectUtils.isEquals(actual, expected)
        }

        /**
         * get length of CharSequence
         *
         *
         * <pre>
         * length(null) = 0;
         * length(\"\") = 0;
         * length(\"abc\") = 3;
        </pre> *
         *
         * @param str
         * @return if str is null or empty, return 0, else return [CharSequence.length].
         */
        fun length(str: CharSequence?): Int {
            return str?.length ?: 0
        }

        /**
         * null Object to empty string
         *
         *
         * <pre>
         * nullStrToEmpty(null) = &quot;&quot;;
         * nullStrToEmpty(&quot;&quot;) = &quot;&quot;;
         * nullStrToEmpty(&quot;aa&quot;) = &quot;aa&quot;;
        </pre> *
         *
         * @param str
         * @return
         */
        fun nullStrToEmpty(str: Any?): String {
            return if (str == null) "" else (if (str is String) str else str.toString())!!
        }

        /**
         * capitalize first letter
         *
         *
         * <pre>
         * capitalizeFirstLetter(null)     =   null;
         * capitalizeFirstLetter("")       =   "";
         * capitalizeFirstLetter("2ab")    =   "2ab"
         * capitalizeFirstLetter("a")      =   "A"
         * capitalizeFirstLetter("ab")     =   "Ab"
         * capitalizeFirstLetter("Abc")    =   "Abc"
        </pre> *
         *
         * @param str
         * @return
         */
        fun capitalizeFirstLetter(str: String): String {
            if (isEmpty(str)) {
                return str
            }
            val c = str[0]
            return if (!Character.isLetter(c) || Character.isUpperCase(c)) str else StringBuilder(
                str.length
            )
                .append(Character.toUpperCase(c)).append(str.substring(1)).toString()
        }

        /**
         * encoded in utf-8
         *
         *
         * <pre>
         * utf8Encode(null)        =   null
         * utf8Encode("")          =   "";
         * utf8Encode("aa")        =   "aa";
         * utf8Encode("啊啊啊啊")   = "%E5%95%8A%E5%95%8A%E5%95%8A%E5%95%8A";
        </pre> *
         *
         * @param str
         * @return
         * @throws UnsupportedEncodingException if an error occurs
         */
        fun utf8Encode(str: String): String {
            return if (!isEmpty(str) && str.toByteArray().size != str.length) {
                try {
                    URLEncoder.encode(str, "UTF-8")
                } catch (e: UnsupportedEncodingException) {
                    throw RuntimeException("UnsupportedEncodingException occurred. ", e)
                }
            } else str
        }

        /**
         * encoded in utf-8, if exception, return defultReturn
         *
         * @param str
         * @param defultReturn
         * @return
         */
        fun utf8Encode(str: String, defultReturn: String): String {
            return if (!isEmpty(str) && str.toByteArray().size != str.length) {
                try {
                    URLEncoder.encode(str, "UTF-8")
                } catch (e: UnsupportedEncodingException) {
                    defultReturn
                }
            } else str
        }

        /**
         * get innerHtml from href
         *
         *
         * <pre>
         * getHrefInnerHtml(null)                                  = ""
         * getHrefInnerHtml("")                                    = ""
         * getHrefInnerHtml("mp3")                                 = "mp3";
         * getHrefInnerHtml("&lt;a innerHtml&lt;/a&gt;")                    = "&lt;a innerHtml&lt;/a&gt;";
         * getHrefInnerHtml("&lt;a&gt;innerHtml&lt;/a&gt;")                    = "innerHtml";
         * getHrefInnerHtml("&lt;a&lt;a&gt;innerHtml&lt;/a&gt;")                    = "innerHtml";
         * getHrefInnerHtml("&lt;a href="baidu.com"&gt;innerHtml&lt;/a&gt;")               = "innerHtml";
         * getHrefInnerHtml("&lt;a href="baidu.com" title="baidu"&gt;innerHtml&lt;/a&gt;") = "innerHtml";
         * getHrefInnerHtml("   &lt;a&gt;innerHtml&lt;/a&gt;  ")                           = "innerHtml";
         * getHrefInnerHtml("&lt;a&gt;innerHtml&lt;/a&gt;&lt;/a&gt;")                      = "innerHtml";
         * getHrefInnerHtml("jack&lt;a&gt;innerHtml&lt;/a&gt;&lt;/a&gt;")                  = "innerHtml";
         * getHrefInnerHtml("&lt;a&gt;innerHtml1&lt;/a&gt;&lt;a&gt;innerHtml2&lt;/a&gt;")        = "innerHtml2";
        </pre> *
         *
         * @param href
         * @return
         *  * if href is null, return ""
         *  * if not match regx, return source
         *  * return the last string that match regx
         *
         */
        fun getHrefInnerHtml(href: String?): String? {
            if (isEmpty(href)) {
                return ""
            }
            val hrefReg = ".*<[\\s]*a[\\s]*.*>(.+?)<[\\s]*/a[\\s]*>.*"
            val hrefPattern = Pattern.compile(hrefReg, Pattern.CASE_INSENSITIVE)
            val hrefMatcher = hrefPattern.matcher(href)
            return if (hrefMatcher.matches()) {
                hrefMatcher.group(1)
            } else href
        }

        /**
         * process special char in html
         *
         *
         * <pre>
         * htmlEscapeCharsToString(null) = null;
         * htmlEscapeCharsToString("") = "";
         * htmlEscapeCharsToString("mp3") = "mp3";
         * htmlEscapeCharsToString("mp3&lt;") = "mp3<";
         * htmlEscapeCharsToString("mp3&gt;") = "mp3\>";
         * htmlEscapeCharsToString("mp3&amp;mp4") = "mp3&mp4";
         * htmlEscapeCharsToString("mp3&quot;mp4") = "mp3\"mp4";
         * htmlEscapeCharsToString("mp3&lt;&gt;&amp;&quot;mp4") = "mp3\<\>&\"mp4";
        </pre> *
         *
         * @param source
         * @return
         */
        fun htmlEscapeCharsToString(source: String): String {
            return if (isEmpty(source)) source else source.replace("&lt;".toRegex(), "<")
                .replace("&gt;".toRegex(), ">")
                .replace("&amp;".toRegex(), "&").replace("&quot;".toRegex(), "\"")
        }

        /**
         * transform half width char to full width char
         *
         *
         * <pre>
         * fullWidthToHalfWidth(null) = null;
         * fullWidthToHalfWidth("") = "";
         * fullWidthToHalfWidth(new String(new char[] {12288})) = " ";
         * fullWidthToHalfWidth("！＂＃＄％＆) = "!\"#$%&";
        </pre> *
         *
         * @param s
         * @return
         */
        fun fullWidthToHalfWidth(s: String): String {
            if (isEmpty(s)) {
                return s
            }
            val source = s.toCharArray()
            for (i in source.indices) {
                if (source[i].toInt() == 12288) {
                    source[i] = ' '
                    // } else if (source[i] == 12290) {
                    // source[i] = '.';
                } else if (source[i].toInt() in 65281..65374) {
                    source[i] = (source[i] - 65248)
                } else {
                    source[i] = source[i]
                }
            }
            return String(source)
        }

        /**
         * transform full width char to half width char
         *
         *
         * <pre>
         * halfWidthToFullWidth(null) = null;
         * halfWidthToFullWidth("") = "";
         * halfWidthToFullWidth(" ") = new String(new char[] {12288});
         * halfWidthToFullWidth("!\"#$%&) = "！＂＃＄％＆";
        </pre> *
         *
         * @param s
         * @return
         */
        fun halfWidthToFullWidth(s: String): String {
            if (isEmpty(s)) {
                return s
            }
            val source = s.toCharArray()
            for (i in source.indices) {
                if (source[i] == ' ') {
                    source[i] = 12288.toChar()
                    // } else if (source[i] == '.') {
                    // source[i] = (char)12290;
                } else if (source[i].toInt() in 33..126) {
                    source[i] = (source[i] + 65248)
                } else {
                    source[i] = source[i]
                }
            }
            return String(source)
        }

        /**
         * 手机号隐藏位数
         *
         * @param mobile
         * @return
         */
        fun getMoblie(mobile: String): String {
            val str1 = mobile.substring(0, 3)
            val str2 = mobile.substring(7, 11)
            return "$str1****$str2"
        }

        /**
         * 字符串转换成日期类型
         *
         * @param str
         * @return
         */
        fun stringToDate(str: String?): Date? {
            val sdf = SimpleDateFormat("yyyy-MM-dd") //小写的mm表示的是分钟
            var date: Date? = null
            try {
                date = sdf.parse(str)
            } catch (e: ParseException) {
                e.printStackTrace()
            }
            return date
        }

        fun formatString(time: String?): String? {
            return if (time == null) {
                null
            } else {
                val startTime = time.replace("T", " ")
                startTime.replace("-", ".")
            }
        }

        fun formatString2(time: String?): String? {
            return if (time == null) {
                null
            } else {
                val startTime = time.replace("T", " ")
                startTime.replace("/", ".")
            }
        }

        /**
         * 判断获取的result
         *
         * @param result
         * @return
         */
        @JvmStatic
        fun isResultOk(result: String): Boolean {
            if (!isEmpty(result)) {
                if (result.equals("ok", ignoreCase = true)) return true
            }
            return false
        }

        @JvmStatic
        fun getLastInt(id: String): Int {
            return if (!isEmpty(id)) id.substring(id.length - 1)
                .toInt() else 0
        }

        /**
         * 把总价格做处理
         *
         * @param price
         * @return
         */
        @JvmStatic
        fun formatPrice(price: String, context: Context): String {
            val dPrice = java.lang.Double.valueOf(price)
            return if (dPrice <= 10000) {
                price
            } else {
                val d = dPrice / 10000
                //保留一位小数
                val result = Math.round(d * 10).toDouble() / 10
                result.toString() + context.resources.getString(R.string.million)
            }
        }

        /**
         * 把总价格做处理
         *
         * @param price
         * @return
         */
        @JvmStatic
        fun formatPrice(price: Int, context: Context): String {
            return if (price <= 10000) {
                price.toString()
            } else {
                val d = (price / 10000).toDouble()
                //保留一位小数
                val result = Math.round(d * 10).toDouble() / 10
                result.toString() + context.resources.getString(R.string.million)
            }
        }

        /**
         * 将给定的字符串给定的长度两端对齐
         *
         * @param str  待对齐字符串
         * @param size 汉字个数，eg:size=5，则将str在5个汉字的长度里两端对齐
         * @Return
         */
        fun justifyString(str: String, size: Int): SpannableStringBuilder {
            val spannableStringBuilder = SpannableStringBuilder()
            if (TextUtils.isEmpty(str)) {
                return spannableStringBuilder
            }
            val chars = str.toCharArray()
            if (chars.size >= size || chars.size == 1) {
                return spannableStringBuilder.append(str)
            }
            val l = chars.size
            val scale = (size - l).toFloat() / (l - 1)
            for (i in 0 until l) {
                spannableStringBuilder.append(chars[i])
                if (i != l - 1) {
                    val s = SpannableString("　") //全角空格
                    s.setSpan(ScaleXSpan(scale), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
                    spannableStringBuilder.append(s)
                }
            }
            return spannableStringBuilder
        }

        fun setSpannableString(
            context: Context,
            allString: Int,
            color: Int,
            vararg formStrings: String?
        ): SpannableStringBuilder {
            return setSpannableString(
                context,
                context.getString(allString),
                intArrayOf(color),
                *formStrings
            )
        }

        fun setSpannableString(
            context: Context,
            allString: String?,
            color: Int,
            vararg formStrings: String?
        ): SpannableStringBuilder {
            return setSpannableString(context, allString, intArrayOf(color), *formStrings)
        }

        fun setSpannableString(
            context: Context,
            allString: String?,
            colors: IntArray,
            vararg formStrings: String?
        ): SpannableStringBuilder {
            var allString = allString
            for (formString in formStrings) {
                allString = String.format(allString!!, formString)
            }
            val sb = StringBuffer(allString)
            val builder = SpannableStringBuilder(sb)
            for (i in 0 until formStrings.size) {
                builder.setSpan(
                    ForegroundColorSpan(context.resources.getColor(if (i < colors.size) colors[i] else colors[colors.size - 1])),
                    sb.indexOf(formStrings[i]),
                    sb.indexOf(formStrings[i]) + formStrings[i]?.length!!,
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
                )
            }
            return builder
        }

        fun formatStupidScoreString(score: String): String {
            if (isBlank(score)) {
                return "0"
            }
            val scoreDouble = score.toDouble()
            val scoreInt = Math.floor(scoreDouble).toInt()
            return formatENotationString(scoreDouble, if (scoreDouble > scoreInt) 1 else 0)
        }

        @JvmStatic
        fun formatENotationString(data: String?, digit: Int): String {
            if (data == null) {
                return "0"
            }
            //格式化数据去除科学计数法，去除无用的0
            var d: Double? = null
            try {
                d = java.lang.Double.valueOf(data)
            } catch (e: NumberFormatException) {
            }
            return getDecimalFormat(digit).format(d)
        }

        @JvmStatic
        fun formatENotationString(data: Double?, digit: Int): String {
            return if (data == null || data == 0.0) {
                "0"
            } else getDecimalFormat(digit).format(data)
        }

        @JvmStatic
        fun formatENotationString(data: Float?, digit: Int): String {
            return if (data == null) {
                "0"
            } else getDecimalFormat(digit)
                .format(data)
        }

        /**
         * 需要保留的位数
         *
         * @param digit
         * @return
         */
        @JvmStatic
        fun getDecimalFormat(digit: Int): DecimalFormat {
            val decimalFormat: DecimalFormat
            decimalFormat = if (digit == 0) {
                DecimalFormat("#")
            } else if (digit == 1) {
                DecimalFormat("#.#")
            } else if (digit == 2) {
                DecimalFormat("#.##")
            } else if (digit == 3) {
                DecimalFormat("#.###")
            } else {
                //保留4位小数
                DecimalFormat("#.####")
            }
            return decimalFormat
        }

        /**
         * 去除小数点后多余的0
         *
         * @return
         */
        @JvmStatic
        fun deleteRedundancyZero(data: String?): String? {
            var data = data
            if (data == null) {
                return null
            }
            if (data.indexOf(".") > 0) {
                //正则表达
                //去掉后面无用的零
                data = data.replace("0+?$".toRegex(), "")
                //如小数点后面全是零则去掉小数点
                data = data.replace("[.]$".toRegex(), "")
                return data
            }
            return data
        }

        @JvmStatic
        fun replaceBlank(str: String?): String {
            var dest = ""
            if (str != null) {
                val p = Pattern.compile("\\s*|\t|\r|\n")
                val m = p.matcher(str)
                dest = m.replaceAll("")
            }
            return dest
        }

        fun isEmojiCharacter(codePoint: Char): Boolean {
            return (!(codePoint.toInt() == 0x0 || codePoint.toInt() == 0x9 || codePoint.toInt() == 0xA || codePoint.toInt() == 0xD
                    || codePoint.toInt() >= 0x20 && codePoint.toInt() <= 0xD7FF) || codePoint.toInt() >= 0xE000 && codePoint.toInt() <= 0xFFFD
                    || codePoint.toInt() >= 0x10000 && codePoint.toInt() <= 0x10FFFF)
        }

        @JvmStatic
        fun keepTwoDigitDecimal(number: Double): Double {
            var bd = BigDecimal(number)
            bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP)
            return bd.toDouble()
        }

        /**
         * 数字按中文习惯转换 xx.x万 xx.x亿
         *
         * @param data
         * @param isInt <10000 是否为整数
         * @return
         */
        @JvmStatic
        fun formatCNNumber(data: Double, context: Context, isInt: Boolean): String {
            return if (data <= 10000) {
                if (isInt) {
                    return data.toString()
                } else {
                    data.toString()
                }
            } else if (data > 10000 && data < 100000000) {
                val result = data / 10000
                formatENotationString(
                    result,
                    2
                ) + context.resources.getString(R.string.million)
            } else {
                val result = data / 100000000
                formatENotationString(
                    result,
                    2
                ) + context.resources.getString(R.string.yi)
            }
        }

        /**
         * 数字按中文习惯转换 xx.x万 xx.x亿
         *
         * @param data
         * @param isInt <10000 是否为整数
         * @return
         */
        @JvmStatic
        fun formatCNNumber(context: Context, data: Double, digit: Int, isInt: Boolean): String {
            return if (data <= 10000) {
                if (isInt) {
                    return data.toString()
                } else {
                    formatENotationString(data, digit)
                }
            } else if (data > 10000 && data < 100000000) {
                val result = data / 10000
                formatENotationString(
                    result,
                    digit
                ) + context.resources.getString(R.string.million)
            } else {
                val result = data / 100000000
                formatENotationString(
                    result,
                    digit
                ) + context.resources.getString(R.string.yi)
            }
        }

        @JvmStatic
        fun formatCNNumber(context: Context, data: Int, digit: Int): String {
            return if (data <= 10000) {
                return data.toString()
            } else if (data > 10000 && data < 100000000) {
                val result = (data / 10000).toDouble()
                formatENotationString(
                    result,
                    digit
                ) + context.resources.getString(R.string.million)
            } else {
                val result = (data / 100000000).toDouble()
                formatENotationString(
                    result,
                    digit
                ) + context.resources.getString(R.string.yi)
            }
        }

        /**
         * 数字按中文习惯转换 xx.x万 xx.x亿
         *
         * @param data
         * @return
         */
        @JvmStatic
        fun formatCNNumber(data: String?, context: Context, isInt: Boolean): String {
            val d = java.lang.Double.valueOf(data)
            return formatCNNumber(d, context, isInt)
        }

        /**
         * 秒转时分秒
         *
         * @param seconds
         * @return
         */
        fun getLiveTime(seconds: Long): String {
            val hs: String
            val ms: String
            val ss: String
            val h: Long
            val m: Long
            val s: Long
            h = seconds / 3600
            m = seconds % 3600 / 60
            s = seconds % 3600 % 60
            hs = if (h < 10) {
                "0$h"
            } else {
                "" + h
            }
            ms = if (m < 10) {
                "0$m"
            } else {
                "" + m
            }
            ss = if (s < 10) {
                "0$s"
            } else {
                "" + s
            }
            return if (hs == "00") {
                "$ms:$ss"
            } else {
                "$hs:$ms:$ss"
            }
        }

        fun getInteger(money: String?): Int {
            return java.lang.Double.valueOf(money).toLong().toInt()
        }

        fun getDecimal(money: String?): Int {
            val x = java.lang.Double.valueOf(money)
            val y = x - x.toInt()
            return (y * 100).toInt()
        }

        @JvmStatic
        fun saveTwoRound(d: Double): String {
            return try {
                val df = DecimalFormat("0.00")
                df.format(d)
            } catch (e: Exception) {
                e.printStackTrace()
                d.toString()
            }
        }

        /**
         * 保留一位小数计算比例
         *
         * @param num1
         * @param num2
         * @return
         */
        fun calculateRatio(num1: Int, num2: Int): String {
            return if (num2 == 0) {
                "100"
            } else {
                formatENotationString(
                    (num1 - num2).toDouble() / num2.toDouble() * 100,
                    1
                )
            }
        }

        /**
         * 限制字符串长度
         *
         * @param str
         * @param maxLen
         * @return
         */
        @JvmStatic
        fun handleText(str: String?, maxLen: Int): String? {
            if (TextUtils.isEmpty(str)) {
                return str
            }
            var count = 0
            var endIndex = 0
            str?.length?.let {
                for (i in str.indices) {
                    val item = str[i]
                    count = if (item.toInt() < 128) {
                        count + 1
                    } else {
                        count + 2
                    }
                    if (maxLen == count || item.toInt() >= 128 && maxLen + 1 == count) {
                        endIndex = i
                    }
                }
            }

            return if (count <= maxLen) {
                str
            } else {
                str?.substring(0, endIndex) + "..."
            }
        }

        /**
         * 限制字符串长度中间省略号
         *
         * @param str
         * @param maxLen
         * @return
         */
        fun handleText2(str: String, maxLen: Int): String {
            if (TextUtils.isEmpty(str)) {
                return str
            }
            var count = 0
            var endIndex = 0
            for (i in 0 until str.length) {
                val item = str[i]
                count = if (item.toInt() < 128) {
                    count + 1
                } else {
                    count + 2
                }
                if (maxLen - 4 == count || item.toInt() >= 128 && maxLen - 4 + 1 == count) {
                    endIndex = i
                }
            }
            return if (count <= maxLen) {
                str
            } else {
                str.substring(0, 6) + "..." + str.substring(str.length - 2)
            }
        }

        fun substringForWidth(str: String, length: Int): String {
            return if (length(str) != 0 && length(
                    str
                ) > length
            ) {
                str.substring(0, length) + "…"
            } else {
                str
            }
        }

        /**
         * 限制字符串长度，过长的直接截掉
         *
         * @param str
         * @param maxLen
         * @return
         */
        @JvmStatic
        fun handleText3(str: String?, maxLen: Int): String? {
            if (TextUtils.isEmpty(str)) {
                return str
            }
            var count = 0
            var endIndex = 0
            str?.length?.let {
                for (i in str.indices) {
                    val item = str[i]
                    count = if (item.toInt() < 128) {
                        count + 1
                    } else {
                        count + 2
                    }
                    if (maxLen == count || item.toInt() >= 128 && maxLen + 1 == count) {
                        endIndex = i
                    }
                }
            }

            return if (count <= maxLen) {
                str
            } else {
                str?.substring(0, endIndex)
            }
        }
    }

    init {
        throw AssertionError()
    }
}